package ${baseService.packageName};

import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

/**
 * 数据库操作BaseService
 *
 * @author MyBatisX Generator
 */
public interface ${'BaseService<Domain extends ' + baseDomain.fileName + ', ColumnEnum extends ' + baseColumnEnum.fileName + '>'} {
    // region MyBatisX Generator

    /**
     * 将指定的集合拆分成指定大小的集合
     *
     * @param coll      待拆分的集合
     * @param splitSize 指定的大小
     * @param ${'<T>'}       集合类型
     * @return 拆分后的集合
     */
    static ${'<T> List<List<T>>'} split(${'Collection<T>'} coll, int splitSize) {
        if (null == coll || coll.isEmpty()) {
            return Collections.emptyList();
        }
        ${'List<List<T>> result = new ArrayList<>();'}
        ${'List<T> container = null;'}
        for (T item : coll) {
            if (null == container) {
                ${'container = new ArrayList<>(splitSize);'}
                result.add(Collections.unmodifiableList(container));
            }

            container.add(item);
            if (container.size() == splitSize) {
                container = null;
            }
        }
        return Collections.unmodifiableList(result);
    }

    /**
     * 获取mapper对象
     *
     * @see BaseMapper
     */
    ${'BaseMapper<Domain>'} getMapper();

    /**
     * 获取sessionFactory对象
     *
     * @return 获取sessionFactory对象
     */
    SqlSessionFactory getSessionFactory();

    /**
     * 获取mapper的类对象
     *
     * @return 获取mapper的类对象
     */
    ${'<T> Class<T>'} getMapperClass();

    /**
     * 保存记录，忽略id,createdAt,updatedAt等字段
     *
     * @param record 待处理的数据
     * @return 更新成功记录数
     * @author MyBatisX Generator
     */
    default int save(Domain record) {
        return this.getMapper().save(record);
    }

    /**
     * 保存记录，仅保留提供了值的字段
     *
     * @param record 待处理的数据
     * @return 更新成功记录数
     * @author MyBatisX Generator
     */
    default int saveSelective(Domain record) {
        return this.getMapper().saveSelective(record);
    }

    /**
     * 保存记录，如果存在主键、唯一键冲突，则进行数据更新
     *
     * @param record 待处理的数据
     * @return 更新成功记录数
     * @author MyBatisX Generator
     */
    default int saveOnDuplicateKey(Domain record) {
        return this.getMapper().saveOnDuplicateKey(record);
    }

    /**
     * 根据record中提供的主键id进行数据更新
     *
     * @param record 待更新的数据
     * @return 更新成功的数量
     * @author MyBatisX Generator
     */
    default int update(Domain record) {
        return this.getMapper().update(record);
    }

    /**
     * 根据主键更新非主键字段
     *
     * @param query 待处理的数据
     * @return 更新成功记录数
     * @author MyBatisX Generator
     */
    default int updateSelectiveByPk(Domain query) {
        return this.getMapper().updateSelectiveByPk(query);
    }

    /**
     * 根据id移除记录，软删除，将deleted设置成1
     *
     * @param pk 待插入的数据集合
     * @return 删除的记录数
     * @author MyBatisX Generator
     */
    default int removeByPk(Long pk) {
        return this.getMapper().removeByPk(pk);
    }

    /**
     * 根据id移除记录，批量软删除，将deleted设置成1
     *
     * @param pkList 待插入的数据集合
     * @return 删除的记录数
     * @author MyBatisX Generator
     */
    default int removeByPkList(${'Collection<Long>'} pkList) {
        return this.getMapper().removeByPkList(pkList);
    }

    /**
     * 根据id删除记录
     *
     * @param pk 待插入的数据集合
     * @return 删除的记录数
     * @author MyBatisX Generator
     */
    default int deleteByPk(Long pk) {
        return this.getMapper().deleteByPk(pk);
    }

    /**
     * 根据id列表批量删除记录
     *
     * @param pkList 待插入的数据集合
     * @return 删除的记录数
     * @author MyBatisX Generator
     */
    default int deleteByPkList(${'Collection<Long>'} pkList) {
        return this.getMapper().deleteByPkList(pkList);
    }

    /**
     * 根据主键，查询记录
     *
     * @param pk 主键
     * @return 更新成功的数量
     * @author MyBatisX Generator
     */
    default Domain get(Long pk) {
        return this.getMapper().get(pk);
    }

    /**
     * 查询条件
     *
     * @param query 查询条件
     * @return 查询记录
     * @author MyBatisX Generator
     */
    default ${'Collection<Domain>'} list(Domain query) {
        return this.getMapper().list(query);
    }

    /**
     * 根据指定的条件、字段名查询对应的字段数据
     *
     * @param query           查询条件
     * @param columnNameEnums 字段名，如果不指定，则查询所有字段
     * @return 查询记录
     * @author MyBatisX Generator
     */
    default ${'Collection<Domain>'} listSpecifiedFields(Domain query, ${'Collection<ColumnEnum>'} columnNameEnums) {
        if (null == columnNameEnums || columnNameEnums.isEmpty()) {
            throw new IllegalArgumentException("查询的字段名不允许为null");
        }

        ${'final Collection<String> columnNames = new HashSet<>(columnNameEnums.size());'}
        for (ColumnEnum columnNameEnum : columnNameEnums) {
            columnNames.add(columnNameEnum.getColumnName());
        }

        return this.getMapper().listSpecifiedFields(query, columnNames);
    }

    /**
     * 批量插入数据
     *
     * @param records 待插入的数据集合
     * @return 插入成功的记录数
     * @author MyBatisX Generator
     */
    default void batchSave(${'Collection<Domain>'} records) {
        this.batchSave(records, 10);
    }

    /**
     * 批量插入数据
     *
     * @param records 待插入的数据集合
     * @return 插入成功的记录数
     * @author MyBatisX Generator
     */
    default void batchSave(${'Collection<Domain> records'}, int batchSize) {
        // 至少100个为一批次
        final int batchSizeInner = Math.max(batchSize, 100);
        final ${'List<List<Domain>>'} split = BaseService.split(records, batchSizeInner);
        try (SqlSession sqlSession = getSessionFactory().openSession(ExecutorType.BATCH)) {
            final ${'BaseMapper<Domain>'} batchMapper = sqlSession.getMapper(getMapperClass());
            for (${'List<Domain>'} item : split) {
                for (Domain domain : item) {
                    batchMapper.saveSelective(domain);
                }
                sqlSession.flushStatements();
            }
        }
    }

    /**
     * 将指定的字段重置为默认值
     *
     * @param pks         主键列表
     * @param columnEnums 字段列表
     * @return 受影响的行数
     * @author MyBatisX Generator
     */
    default int resetDefaultVal(${'Collection<Long>'} pks, ${'Collection<ColumnEnum>'} columnEnums) {
        if (null == columnEnums || columnEnums.isEmpty()) {
            return 0;
        }
        ${'final Collection<String> columnNames = new HashSet<>(columnEnums.size());'}
        for (ColumnEnum item : columnEnums) {
            columnNames.add(item.getColumnName());
        }
        return this.getMapper().resetDefaultVal(pks, columnNames);
    }
    // endregion MyBatisX Generator

}
